const webpack = require('webpack')
const fs = require('fs')
const path = require('path')
const middleware = require("webpack-dev-middleware")
const HMR = require("webpack-hot-middleware")
const MFS = require('memory-fs')

const clientConfig = require('./webpack.client.config')
const serverConfig = require('./webpack.server.config')

const readFile = (fs, file) => {
    try {
        return fs.readFileSync(path.join(clientConfig.output.path, file), 'utf8')
    } catch (error) {
        console.log('error: ', error);
    }
}

const setupServer = (app, templatePath, cb) => {
    let bundle
    let clientManifest
    let template
    let ready
    const readyPromise = new Promise(r => ready = r)

    template = fs.readFileSync(templatePath, 'utf8')
    const update = () => {
        if (bundle && clientManifest) {
            // 通知 server 进行渲染
            // 执行 createRenderer -> RenderToString
            ready()
            cb(bundle, {
                template,
                clientManifest
            })
        }
    }

    // modify client config to work with hot middleware
    clientConfig.entry.app = ['webpack-hot-middleware/client', clientConfig.entry.app]
    clientConfig.output.filename = '[name].js'
    clientConfig.plugins.push(
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoEmitOnErrorsPlugin()
    )
    // dev middleware
	//  console.log("clientCompiler start")
    const clientCompiler = webpack(clientConfig);
    const devMiddleware = middleware(clientCompiler, {
        noInfo: true, 
        publicPath: clientConfig.output.publicPath, 
        logLevel: 'silent',
        serverSideRender: true
    })
    app.use(devMiddleware);

    clientCompiler.hooks.done.tap('done', stats => {
        stats = stats.toJson()
        stats.errors.forEach(err => console.error(err))
        stats.warnings.forEach(err => console.warn(err))
        if (stats.errors.length) return
        clientManifest = JSON.parse(readFile(
            devMiddleware.fileSystem,
            'vue-ssr-client-manifest.json'
        ))
        update()
    })
    // hot middleware
    app.use(HMR(clientCompiler));

    // webpack -> entry-server -> bundle
    const mfs = new MFS();
    const serverCompiler = webpack(serverConfig);
    // watch and update server renderer
    serverCompiler.outputFileSystem = mfs;
    serverCompiler.watch({}, (err, stats) => {
        if (err) throw err
        // 之后读取输出：
        stats = stats.toJson()
        stats.errors.forEach(err => console.error(err))
        stats.warnings.forEach(err => console.warn(err))
        if (stats.errors.length) return
        // read bundle generated by vue-ssr-webpack-plugin
        bundle = JSON.parse(readFile(mfs, 'vue-ssr-server-bundle.json'))
        update()
    });

    return readyPromise
}

module.exports = setupServer
